package com.bizdk.fastfx.controller;

import com.bizdk.fastfx.fxsupport.FxmlView;
import com.bizdk.fastfx.fxsupport.JavaFxController;
import com.bizdk.fastfx.model.PatientModel;
import com.bizdk.fastfx.service.PatientService;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.*;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.UUID;

@Controller
@FxmlView("/view/ImageViewerState.fxml")
public class ImageViewerStageController extends JavaFxController {
    @FXML
    private ImageView iv_main;

    @FXML
    private AnchorPane ap_main;

    @FXML
    private ScrollPane sp_main;

    @FXML
    private HBox hb_thumbnail;

    @Autowired
    private MainStageController mainStageController;

    @Autowired
    private PatientService patientService;

    private PatientModel model;

    private Parent root;

    private double scaleFactor = 1.0D;
    private double startDragX;
    private double startDragY;
    private Rectangle selectionRectangle;

    public void initialize(URL location, ResourceBundle resources) {
        getStage().setResizable(false);

        // 注册窗口关闭事件，用来保存图片
        getStage().setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent event) {
                handlerWindowClose(event);
            }
        });

        iv_main.setPreserveRatio(true);
        iv_main.setSmooth(true);

        // Create a selection rectangle
        selectionRectangle = new Rectangle(0, 0, 0, 0);
        selectionRectangle.setStroke(Color.RED);
        selectionRectangle.setFill(Color.TRANSPARENT);
        selectionRectangle.setStrokeWidth(2.0);
        ap_main.getChildren().add(selectionRectangle);

        // 禁用默认滚轮事件
        sp_main.setOnScroll(null);

        // 禁用默认滚轮事件
        sp_main.setOnScroll(null);
        // 自定义滚轮事件
        sp_main.addEventFilter(ScrollEvent.ANY, event -> {
            event.consume();
            // 根据滚轮方向调整缩放倍数的值
            scaleFactor += event.getDeltaY() > 0 ? 0.1D : -0.1D;
            zoomImage(scaleFactor);
        });

        // 监听鼠标拖拽事件，实现拖动
        ap_main.setOnMousePressed(this::handlerMousePressed);
        ap_main.setOnMouseDragged(this::handlerMouseDragged);
        ap_main.setOnMouseReleased(this::handlerMouseReleased);
    }


    public void handlerWindowClose(WindowEvent event) {
        patientService.updateModel(model);
    }

    public void handlerRightRotate(ActionEvent event) {
        event.consume();
        if (iv_main.getImage() != null) {
            iv_main.setRotate(iv_main.getRotate() + 90);
        }
    }

    public void handlerLeftRotate(ActionEvent event) {
        event.consume();
        if (iv_main.getImage() != null) {
            iv_main.setRotate(iv_main.getRotate() - 90);
        }
    }

    public void handlerZoomIn(ActionEvent event) {
        event.consume();
        scaleFactor = 0.5;
        zoomImage(scaleFactor);
    }

    public void handlerZoomOut(ActionEvent event) {
        event.consume();
        scaleFactor = 1.5;
        zoomImage(scaleFactor);
    }

    public void handlerMousePressed(MouseEvent event) {
        event.consume(); // 防止传递到 ImageView 导致拖动失败
        if (MouseButton.PRIMARY.equals(event.getButton())) {
            startDragX = event.getX();
            startDragY = event.getY();
        }

        if (MouseButton.SECONDARY.equals(event.getButton())) {
            selectionRectangle.setX(event.getX());
            selectionRectangle.setY(event.getY());
            selectionRectangle.setWidth(0);
            selectionRectangle.setHeight(0);
        }
    }

    public void handlerMouseDragged(MouseEvent event) {
        event.consume(); // 防止传递到 ImageView 导致拖动失败
        if (MouseButton.PRIMARY.equals(event.getButton())) {
            double x = event.getX();
            double y = event.getY();
            // 移动x，y距离
            double moveX = x - startDragX;
            double moveY = y - startDragY;
            double newX = iv_main.getTranslateX() + moveX;
            double newY = iv_main.getTranslateY() + moveY;
            // 更新图片的位移坐标
            iv_main.setTranslateX(newX);
            iv_main.setTranslateY(newY);
            // 更新起始位置
            startDragX = x;
            startDragY = y;
        }

        // 鼠标右键
        if (MouseButton.SECONDARY.equals(event.getButton())) {
            selectionRectangle.setWidth(event.getX() - selectionRectangle.getX());
            selectionRectangle.setHeight(event.getY() - selectionRectangle.getY());
        }
    }


    public void handlerMouseReleased(MouseEvent event) {
        event.consume();
        if (MouseButton.SECONDARY.equals(event.getButton())) {
            // 根据红框选取生成选区
            Bounds selectionBounds = new BoundingBox(
                    selectionRectangle.getX(),
                    selectionRectangle.getY(),
                    selectionRectangle.getWidth(),
                    selectionRectangle.getHeight()
            );
            // 构造快照参数
            SnapshotParameters snapshotParams = new SnapshotParameters();
            snapshotParams.setViewport(new Rectangle2D(selectionBounds.getMinX(), selectionBounds.getMinY(),
                    selectionBounds.getWidth(), selectionBounds.getHeight()));
            // 生成快照图片
            Image selectedImage = iv_main.snapshot(snapshotParams, null);
            ImageView selectedImageView = new ImageView(selectedImage);

            StackPane panel = new StackPane(selectedImageView);

            ButtonType saveButtonType = new ButtonType("保存", ButtonBar.ButtonData.OK_DONE);

            Dialog<Image> dialog = new Dialog<>();
            dialog.setTitle("保存图片");
            dialog.getDialogPane().getButtonTypes().addAll(saveButtonType, ButtonType.CANCEL);
            dialog.getDialogPane().setContent(panel);

            dialog.setResultConverter(dialogButton -> {
                if (dialogButton == saveButtonType) {
                    // 保存并放到缩略图列表
                    addAndShowOnThumbnail(selectedImage);
                }
                return null;
            });

            dialog.show();

            // 重置红色选框
            selectionRectangle.setWidth(0);
            selectionRectangle.setHeight(0);
            selectionRectangle.setX(0);
            selectionRectangle.setY(0);
        }
    }

    private void zoomImage(double scaleFactor) {
        // 最小缩放到0.1倍
        // 最大放大10倍
        scaleFactor = Math.max(scaleFactor, 0.1);
        scaleFactor = Math.min(scaleFactor, 10.0);
        iv_main.setScaleX(scaleFactor);
        iv_main.setScaleY(scaleFactor);
    }

    public void clearImageView() {
        hb_thumbnail.getChildren().clear();
        iv_main.setImage(null);
    }

    public void showImage(ImageView thumbnail) {
        if (null != thumbnail) {
            Image image = thumbnail.getImage();
            iv_main.setImage(image);
            iv_main.setFitWidth(image.getWidth());
            iv_main.setFitHeight(image.getHeight());
            resetMianImageView();
        }
    }


    /**
     * 添加并显示到缩略图栏
     *
     * @param image
     */
    public void addAndShowOnThumbnail(Image image) {
        if (null == image) {
            return;
        }

        // 保存图片
        String path = "images" + File.separatorChar + UUID.randomUUID().toString().replaceAll("-", "") + ".png";
        BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
        File file = new File(path);
        try {
            ImageIO.write(bImage, "png", file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ImageView thumbnail = new ImageView(image);
        thumbnail.setFitHeight(100);
        thumbnail.setFitWidth(100);
        thumbnail.setUserData(path);
        hb_thumbnail.getChildren().add(thumbnail);
        addImageViewClickEvent(thumbnail);

        model.getImageViews().add(thumbnail);
    }

    public void show(PatientModel model) {
        this.model = model;
        if (null == model || null == model.getImageViews()) {
            return;
        }

        Stage stage = getStage();
        if (null == stage) {
            stage = new Stage();
            stage.initOwner(mainStageController.getStage()); //设置两个窗口关联，s2窗口的拥有者为s1
            stage.initModality(Modality.WINDOW_MODAL); //s2设置模块化，对s1窗口起作用
            setStage(stage);
        }
        Scene scene = getScene();
        if (null == scene) {
            scene = new Scene(getRoot());
            setScene(scene);
        } else {
            scene.setRoot(getRoot());
        }
        stage.setScene(scene);
        stage.centerOnScreen();
        stage.show();

        iv_main.setImage(null);
        clearImageView();
        for (ImageView thumbnail : model.getImageViews()) {
            thumbnail.setFitHeight(100);
            thumbnail.setFitWidth(100);
            hb_thumbnail.getChildren().add(thumbnail);
            addImageViewClickEvent(thumbnail);
        }
    }

    private void addImageViewClickEvent(ImageView thumbnail) {
        thumbnail.setOnMouseClicked(event -> {
            showImage(thumbnail);
        });
    }

    /**
     * 重置ImageView状态
     */
    private void resetMianImageView(){
        iv_main.setX(0D);
        iv_main.setY(0D);
        iv_main.setLayoutY(0D);
        iv_main.setLayoutY(0D);
        iv_main.setTranslateX(0D);
        iv_main.setTranslateY(0D);
        iv_main.setRotate(0D);
        iv_main.setScaleX(1D);
        iv_main.setScaleY(1D);
    }
}